home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 April: Mac OS SDK / Dev.CD Apr 99 SDK1.toast / Development Kits / QuickTake Digital Camera / QuickTake⁄Windows SDK / QTKSAMPL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-14  |  20.7 KB  |  755 lines  |  [TEXT/mdos]

  1. /*******************************************************************************
  2.  * QTKSAMPL.C version 1.0
  3.  * Copyright Apple Computer, Inc. 1993 -1995, All Rights Reserved.
  4.  *******************************************************************************/
  5.  
  6. /**************************************************************************** 
  7.     PROGRAM: QTKSampl.c
  8.     VERSION: 1.0
  9.  
  10.     PURPOSE: QuickTake sample application.
  11.  
  12.     FUNCTIONS:
  13.  
  14.     WinMain() - Calls initialization function, processes message loop
  15.     InitApplication() - Initializes window data and registers window
  16.     InitInstance() - Saves instance handle and creates main window
  17.     MainWndProc() - Processes messages
  18.  
  19.     CAMERA FUNCTIONS:
  20.         
  21.     CameraInitialize() - Connects to camera and load infomation
  22.     CameraTerminet() - Terminates camera connection
  23.     CameraUnloadThumbnail() - Unloads memory allocated for thumbnail
  24.     CameraLoadThumbnail() - Allocates memory for thumbnail and load 
  25.                             thumbnail data from camera
  26.     CameraPaintThumbnail() - Paint thumbnail
  27.     CameraUnloadPicture() - Unloads memory allocated for picture
  28.     CameraLoadPicture() - Allocates memory for picture and load 
  29.                             picture data from camera
  30.     CameraPaintPicture() - Paint picture
  31.     CameraError() - Camera error message box.
  32.  
  33. ****************************************************************************/
  34.  
  35. #include "qtksampl.h"            /* specific to this program             */
  36.  
  37. HANDLE            hInst;                // This instance
  38. HWND            hMainWnd;            // Handle to main Window
  39. BOOL            bCameraInitialized;    // Whether camera is initialized?
  40. QTKCameraInfo    qtkInfo = {0};        // CameraInfo
  41. CmPictureInfo    pictInfo;            // PictureInfo of last picture
  42. char             cmThumb[2400];        // Data used to store thumbnail data
  43. char            ipm[kIPMContextSize];
  44. HANDLE            hThumbnail;            // Handle to thumbnail data
  45. HANDLE            hPicture;            // Handle to picture data
  46.  
  47.  
  48.  
  49. /****************************************************************************
  50.  
  51.     FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  52.  
  53.     PURPOSE: calls initialization function, processes message loop
  54.  
  55. ****************************************************************************/
  56.  
  57. int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  58. HANDLE hInstance;                 /* current instance         */
  59. HANDLE hPrevInstance;             /* previous instance         */
  60. LPSTR lpCmdLine;                 /* command line             */
  61. int nCmdShow;                     /* show-window type (open/icon) */
  62. {
  63.     MSG msg;                     /* message                 */
  64.  
  65.     if (hPrevInstance)             /* Only one instance of app allowed */
  66.         return (FALSE);
  67.  
  68.     /* Perform initializations of application */
  69.     
  70.     if (!InitApplication(hInstance))
  71.         return (FALSE);
  72.  
  73.     /* Perform initializations of this instance */
  74.     
  75.     if (!InitInstance(hInstance, nCmdShow))
  76.         return (FALSE);
  77.  
  78.     /* Acquire and dispatch messages until a WM_QUIT message is received. */
  79.  
  80.     while (GetMessage(
  81.                 &msg,            // Message structure                 
  82.                 NULL,            // Handle of window receiving the message
  83.                 NULL,            // Lowest message to examine             
  84.                 NULL))            // Highest message to examine        
  85.     {
  86.         TranslateMessage(&msg);    // Translates virtual key codes         
  87.         DispatchMessage(&msg);    // Dispatches message to window         
  88.     }
  89.     return (msg.wParam);        // Returns the value from PostQuitMessage
  90. }
  91.  
  92.  
  93. /****************************************************************************
  94.  
  95.     FUNCTION: InitApplication(HANDLE)
  96.  
  97.     PURPOSE: Initializes window data and registers window class
  98.  
  99. ****************************************************************************/
  100.  
  101. BOOL InitApplication(hInstance)
  102. HANDLE hInstance;                   /* current instance         */
  103. {
  104.     WNDCLASS  wc;
  105.  
  106.     /* Fill in window class structure with parameters that describe the       */
  107.     /* main window.                                                           */
  108.  
  109.     wc.style = NULL;                    /* Class style(s).                    */
  110.     wc.lpfnWndProc = MainWndProc;       /* Function to retrieve messages for  */
  111.                                         /* windows of this class.             */
  112.     wc.cbClsExtra = 0;                  /* No per-class extra data.           */
  113.     wc.cbWndExtra = 0;                  /* No per-window extra data.          */
  114.     wc.hInstance = hInstance;            /* Application that owns the class.   */
  115.     wc.hIcon = NULL;
  116.     wc.hCursor = NULL;
  117.     wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  118.     wc.lpszMenuName =  "QuickTakeSampleMenu";    /* Name of menu resource in .RC file. */
  119.     wc.lpszClassName = "QuickTakeSampleClass";    /* Name used in call to CreateWindow. */
  120.  
  121.     /* Register the window class and return success/failure code. */
  122.  
  123.     return (RegisterClass(&wc));
  124. }
  125.  
  126.  
  127. /****************************************************************************
  128.  
  129.     FUNCTION:  InitInstance(HANDLE, int)
  130.  
  131.     PURPOSE:  Saves instance handle and creates main window
  132.  
  133. ****************************************************************************/
  134.  
  135. BOOL InitInstance(hInstance, nCmdShow)
  136.     HANDLE          hInstance;          /* Current instance identifier.       */
  137.     int             nCmdShow;           /* Param for first ShowWindow() call. */
  138. {
  139.     /* Save the instance handle in static variable, which will be used in  */
  140.     /* many subsequence calls from this application to Windows.            */
  141.  
  142.     hInst = hInstance;
  143.  
  144.     /* Create a main window for this application instance.  */
  145.  
  146.     hMainWnd = CreateWindow(
  147.         "QuickTakeSampleClass",            // See RegisterClass() call.         
  148.         "QuickTake Sample Application",    // Text for window title bar.        
  149.            WS_OVERLAPPEDWINDOW,            // Window style.                     
  150.            CW_USEDEFAULT,                  // Default horizontal position.      
  151.            CW_USEDEFAULT,                  // Default vertical position.        
  152.            CW_USEDEFAULT,                  // Default width.                    
  153.            CW_USEDEFAULT,                  // Default height.                   
  154.            NULL,                           // Overlapped windows have no parent.
  155.            NULL,                           // Use the window class menu.        
  156.            hInstance,                      // This instance owns this window.   
  157.            NULL                            // Pointer not needed.               
  158.     );
  159.  
  160.     /* If window could not be created, return "failure" */
  161.  
  162.     if (!hMainWnd)
  163.         return (FALSE);
  164.  
  165.     /* Make the window visible; update its client area; and return "success" */
  166.  
  167.     ShowWindow(hMainWnd, nCmdShow);  // Show the window                      
  168.     UpdateWindow(hMainWnd);          // Sends WM_PAINT message               
  169.     return (TRUE);
  170.  
  171. }
  172.  
  173. /****************************************************************************
  174.  
  175.     FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM)
  176.  
  177.     PURPOSE:  Processes messages
  178.  
  179. ****************************************************************************/
  180.  
  181. long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
  182. HWND hWnd;                      /* window handle             */
  183. UINT message;                /* type of message         */
  184. WPARAM wParam;                /* additional information           */
  185. LPARAM lParam;                /* additional information           */
  186. {
  187.     switch (message) 
  188.     {
  189.     case WM_CREATE:
  190.         bCameraInitialized = FALSE;
  191.         hThumbnail = 0;
  192.         hPicture = 0;
  193.         break;
  194.  
  195.     case WM_INITMENU:
  196.         break;
  197.  
  198.     case WM_COMMAND:       /* message: command from application menu */
  199.  
  200.         switch(wParam) 
  201.         {
  202.         case IDM_OPEN:
  203.  
  204.             if (bCameraInitialized)
  205.                 break;
  206.             if (CameraInitialize(hInst) == 0)
  207.             {
  208.                 bCameraInitialized = TRUE;
  209.                 hThumbnail = CameraLoadThumbnail();
  210.                 hPicture = CameraLoadPicture();
  211.                 InvalidateRect(hWnd, NULL, TRUE);
  212.             }
  213.             else
  214.                 CameraTerminate();
  215.             break;
  216.         }
  217.         break;
  218.  
  219.     case WM_PAINT:
  220.     
  221.         {
  222.             PAINTSTRUCT ps;
  223.  
  224.             BeginPaint(hWnd, (LPPAINTSTRUCT)&ps);
  225.             CameraPaintThumbnail(ps.hdc, hThumbnail, 0, 0);
  226.             CameraPaintPicture(
  227.                     ps.hdc,
  228.                     hPicture,
  229.                     qtkInfo.cameraInfo.thumbnailImageWidth,
  230.                     0);
  231.             EndPaint (hWnd, (LPPAINTSTRUCT) &ps);
  232.             return (TRUE);
  233.             break;
  234.         }
  235.  
  236.     case WM_DESTROY:          /* message: window being destroyed */
  237.  
  238.         if (bCameraInitialized)
  239.         {
  240.             CameraUnloadPicture(hPicture);
  241.             CameraUnloadThumbnail(hThumbnail);
  242.             CameraTerminate();
  243.         }
  244.         PostQuitMessage(0);
  245.         break;
  246.  
  247.     default:              /* Passes it on if unproccessed    */
  248.         return (DefWindowProc(hWnd, message, wParam, lParam));
  249.     }
  250.     return (NULL);
  251. }
  252.  
  253.  
  254. /****************************************************************************
  255.  
  256.     FUNCTION:    CameraInitialize(HANDLE)
  257.  
  258.     PURPOSE:    Open driver, Connect camera to port, Get cameraInfo,
  259.                 GetPictureInfo
  260.  
  261.     RETURN:        0, if no error 
  262.                 otherwise, error code return from QuickTake driver or ipm
  263.  
  264. ****************************************************************************/
  265.  
  266. OSErr CameraInitialize(HANDLE hInst)
  267. {
  268.     OSErr err;
  269.     int currPort;
  270.     int commPort = 0;        // 0 - Test all ports (1-4)
  271.     int nPicturesTaken;
  272.  
  273.     // Open QuickTake Driver
  274.     qtkInfo.cameraData = hInst;
  275.     err = CmOpenDriver(&qtkInfo.cameraData);
  276.     if (err)
  277.     {
  278.         qtkInfo.cameraData = 0;
  279.         return CameraError("OpenDriver", err);
  280.     }
  281.  
  282.     // Connect camera to port
  283.     for (currPort = 1; currPort <= 4; currPort++)
  284.     {
  285.         CmPortInfoHandlePtr    portInfoPtr;        // handle for modem port
  286.  
  287.         portInfoPtr   = &qtkInfo.portHandle;
  288.  
  289.         // Check to see if this is a port we should check
  290.         if ((commPort == 0) || (currPort == commPort))
  291.         {
  292.             // Get the port info...
  293.             err = CmGetPortInfo(qtkInfo.cameraData, currPort, portInfoPtr);
  294.             if (err == 0)
  295.             {
  296.                 // Is the port availalble?
  297.                 if ((**portInfoPtr)->portStatus & 0x00000001L)
  298.                 {
  299.                     // Port available, try to connect
  300.                     err = CmConnect(qtkInfo.cameraData, *portInfoPtr);
  301.                     if (err == 0)
  302.                     {
  303.                         qtkInfo.connectedPort = currPort;
  304.                         break;
  305.                     }
  306.                     else
  307.                     {
  308.                         CmDisposePortInfo(qtkInfo.cameraData, *portInfoPtr);
  309.                         *portInfoPtr   = NULL;
  310.                     }
  311.                 }
  312.             }
  313.         }
  314.     }
  315.     if (qtkInfo.connectedPort == 0)
  316.         return CameraError("ConnectCamera", err);
  317.  
  318.     // Check camera ready?
  319.     err = CmCheckIfReady(qtkInfo.cameraData);
  320.     if (err)
  321.         return CameraError("CameraReady", err);
  322.  
  323.     // Get camera info
  324.     err = CmGetCameraInfo(qtkInfo.cameraData, &qtkInfo.cameraInfo);
  325.     if (err)
  326.         return CameraError("CameraGetInfo", err);
  327.  
  328.     // Check whether there is at least one picture in the camera
  329.     nPicturesTaken = qtkInfo.cameraInfo.noPicturesTaken;
  330.     if (nPicturesTaken == 0)
  331.         return CameraError("CameraEmpty", 0);
  332.  
  333.     // Get last picture info
  334.      err = CmGetPictureInfo(qtkInfo.cameraData, nPicturesTaken, &pictInfo);
  335.     if (err)
  336.         return CameraError("CameraGetPictureInfo", err);
  337.  
  338.     return err;
  339. }
  340.  
  341.  
  342. /****************************************************************************
  343.  
  344.     FUNCTION:    CameraTerminate(void)
  345.  
  346.     PURPOSE:    Disconnect camera, Close driver
  347.  
  348.     RETURN:        0
  349.  
  350. ****************************************************************************/
  351.  
  352. OSErr CameraTerminate(void)
  353. {
  354.     // Disconnect 
  355.     if (qtkInfo.cameraData)
  356.     {
  357.         if (qtkInfo.connectedPort > 0)
  358.         {
  359.             // Disconnect camera
  360.             CmDisconnect(qtkInfo.cameraData);
  361.             qtkInfo.connectedPort = 0;
  362.  
  363.             // Dispose PortInfo
  364.             CmDisposePortInfo(qtkInfo.cameraData, qtkInfo.portHandle);
  365.             qtkInfo.portHandle = 0;
  366.         }
  367.     }
  368.  
  369.     // Close driver
  370.     if (qtkInfo.cameraData)
  371.     {
  372.         CmCloseDriver(qtkInfo.cameraData);
  373.         qtkInfo.cameraData = 0;
  374.     }
  375.     return 0;
  376. }
  377.  
  378.  
  379. /****************************************************************************
  380.  
  381.     FUNCTION:    CameraUnloadThumbnail(HANDLE)
  382.  
  383.     PURPOSE:    Free up memory allocated for thumbnail.
  384.               
  385.  
  386. ****************************************************************************/
  387.  
  388. void CameraUnloadThumbnail(HANDLE hThumbnail)
  389. {
  390.     GlobalFree(hThumbnail);
  391. }
  392.  
  393. /****************************************************************************
  394.  
  395.     FUNCTION:    CameraLoadThumbnail(void)
  396.  
  397.     PURPOSE:    Allocate memory for the thumbnail and load the thumbnail 
  398.                 of the last picture in the camera into memory.
  399.  
  400.     RETURN:        0, if error
  401.                 otherwise, memory handle to thumbnail data.
  402.  
  403. ****************************************************************************/
  404.  
  405. HANDLE CameraLoadThumbnail(void)
  406. {
  407.     OSErr err;
  408.     long bytesRead;
  409.     DWORD szThumbnail;
  410.     HANDLE hThumbnail;
  411.     BufferPtr pThumbnail;
  412.  
  413.     // Load compressed thumbnail data
  414.     err = CmGetThumbnailImage(
  415.                 qtkInfo.cameraData, 
  416.                 pictInfo.pictureNo,
  417.                 cmThumb,
  418.                 2400,
  419.                 TRUE,
  420.                 &bytesRead);
  421.     if (err)
  422.     {
  423.         CameraError("LoadThumbnail", err);
  424.         return 0;
  425.     }
  426.  
  427.     // Allocate memory for thumbnail image
  428.     szThumbnail = qtkInfo.cameraInfo.thumbnailImageWidth * 3 * 
  429.                     qtkInfo.cameraInfo.thumbnailImageHeight;
  430.     hThumbnail = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, szThumbnail);
  431.     if (hThumbnail == 0)
  432.     {
  433.         CameraError("LoadThumbnail", kCmNoMemoryError);
  434.         return 0;
  435.     }
  436.     pThumbnail = GlobalLock(hThumbnail);
  437.     if (pThumbnail == 0)
  438.     {
  439.         GlobalFree(hThumbnail);
  440.         CameraError("LoadThumbnail", kCmNoMemoryError);
  441.         return 0;
  442.     }
  443.  
  444.     // Convert from compressed thumbnail to thumbnail image
  445.     err = IpInitIPM(ipm);
  446.     if (err == 0)
  447.     {
  448.         // Calculate color table
  449.         err = IpCalculateColorTables(ipm);
  450.         if (err == 0)
  451.         {
  452.             ImageAttribute attr;
  453.  
  454.             // Prepare image attributes 
  455.             attr.aImgWidth = qtkInfo.cameraInfo.thumbnailImageWidth;
  456.             attr.aImgLength = qtkInfo.cameraInfo.thumbnailImageHeight;
  457.             attr.aPixelType = kDIB24;
  458.             attr.aAngle     = kImgRot0;
  459.             attr.aStartingLine = 0;
  460.             attr.aLinesPerBand = 0;
  461.             attr.firstBand = TRUE;
  462.             attr.lastBand  = TRUE;
  463.             attr.aCompressionType = qtkInfo.cameraInfo.thumbImageDatCompMode;
  464.  
  465.             // Convert
  466.             err = IpConvertThumbnailToRGB(
  467.                             ipm, 
  468.                             cmThumb, 
  469.                             pThumbnail, 
  470.                             &attr);
  471.         }
  472.         IpEndIPM(ipm);
  473.     }
  474.     if (err)
  475.     {
  476.         CameraError("LoadThumbnail", err);
  477.         GlobalUnlock(hThumbnail);
  478.         GlobalFree(hThumbnail);
  479.         return 0;
  480.     }
  481.     else
  482.     {
  483.         GlobalUnlock(hThumbnail);
  484.         return hThumbnail;
  485.     }
  486. }
  487.  
  488. /****************************************************************************
  489.  
  490.     FUNCTION:    CameraPaintThumbnail(HDC, HANDLE, int, int)
  491.  
  492.     PURPOSE:    Paint the thumbnail as bitmap.
  493.  
  494. ****************************************************************************/
  495.  
  496. void CameraPaintThumbnail(
  497.     HDC hDC,                 // Handle to display context
  498.     HANDLE hThumbnail,         // Handle to thumbnail memory
  499.     int x,                     // Horizontal offset
  500.     int y)                    // Vertical offset
  501. {
  502.     BITMAPINFO bmpInfo;        // BitmapInfo for display
  503.     LPSTR pThumbnail;        // Thumbnail memory pointer
  504.  
  505.     if (!hThumbnail)
  506.         return;
  507.     bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  508.     bmpInfo.bmiHeader.biWidth = qtkInfo.cameraInfo.thumbnailImageWidth;
  509.     bmpInfo.bmiHeader.biHeight = qtkInfo.cameraInfo.thumbnailImageHeight;
  510.     bmpInfo.bmiHeader.biPlanes = 1;
  511.     bmpInfo.bmiHeader.biBitCount = 24;
  512.     bmpInfo.bmiHeader.biCompression = BI_RGB;
  513.     bmpInfo.bmiHeader.biSizeImage = bmpInfo.bmiHeader.biHeight * 
  514.                                     bmpInfo.bmiHeader.biWidth * 3;
  515.     bmpInfo.bmiHeader.biClrUsed = 0;
  516.     bmpInfo.bmiHeader.biClrImportant = 0;
  517.     bmpInfo.bmiHeader.biXPelsPerMeter = 0;
  518.     bmpInfo.bmiHeader.biYPelsPerMeter = 0;
  519.  
  520.     pThumbnail = GlobalLock(hThumbnail);
  521.     
  522.  
  523.     SetDIBitsToDevice(hDC, x, y, 
  524.                       (WORD)bmpInfo.bmiHeader.biWidth, 
  525.                       (WORD)bmpInfo.bmiHeader.biHeight,
  526.                       0, 0, 0, (WORD)bmpInfo.bmiHeader.biHeight,
  527.                       pThumbnail, &bmpInfo, DIB_RGB_COLORS);
  528.     GlobalUnlock(hThumbnail);
  529. }
  530.  
  531. /****************************************************************************
  532.  
  533.     FUNCTION:    CameraUnloadPicture(HANDLE)
  534.  
  535.     PURPOSE:    Free up memory allocated for picture image.
  536.               
  537.  
  538. ****************************************************************************/
  539.  
  540. void CameraUnloadPicture(HANDLE hPicture)
  541. {
  542.     GlobalFree(hPicture);
  543. }
  544.  
  545.  
  546. /****************************************************************************
  547.  
  548.     FUNCTION:    IPMProgressCallback(short, short, long)
  549.  
  550.     PURPOSE:    Callback function for IPM do update progress.
  551.  
  552.     RETURN:        0
  553.  
  554. ****************************************************************************/
  555.  
  556. static OSErr far pascal IPMProgressCallback
  557.     (
  558.         short msg, 
  559.         short percent, 
  560.         long refcon
  561.     )
  562. {
  563.     if (msg == 1)
  564.         percent = percent;        // Do nothing in this app
  565.     return 0;
  566. }
  567.  
  568. /****************************************************************************
  569.  
  570.     FUNCTION:    CameraLoadPicture(void)
  571.  
  572.     PURPOSE:    Allocate memory for the picture and load the 
  573.                 last picture in the camera into memory.
  574.  
  575.     RETURN:        0, if error
  576.                 otherwise, memory handle to picture data.
  577.  
  578. ****************************************************************************/
  579.  
  580. HANDLE CameraLoadPicture(void)
  581. {
  582.     HANDLE hCmImage;
  583.     BufferPtr pCmImage;
  584.     DWORD szCmImage;
  585.     HANDLE hImage;
  586.     unsigned char huge *pImage;
  587.     DWORD szImage;
  588.     long bytesRead;
  589.     OSErr err;
  590.  
  591.     // Allocate compressed image memory
  592.     szCmImage = pictInfo.imageDataSize;
  593.     hCmImage  = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, szCmImage);
  594.     if (hCmImage == 0)
  595.     {
  596.         CameraError("LoadThumbnail", kCmNoMemoryError);
  597.         return 0;
  598.     }
  599.     pCmImage = (BufferPtr)GlobalLock(hCmImage);
  600.     if (pCmImage == 0)
  601.     {
  602.         GlobalFree(hCmImage);
  603.         CameraError("LoadPicture", kCmNoMemoryError);
  604.         return 0;
  605.     }
  606.  
  607.     // Get compressed image from camera
  608.     err = CmGetFullSizeImage(
  609.                 qtkInfo.cameraData, 
  610.                 pictInfo.pictureNo,
  611.                 pCmImage, 
  612.                 szCmImage, 
  613.                 TRUE, 
  614.                 &bytesRead);
  615.     if (err)
  616.     {
  617.         GlobalUnlock(hCmImage);
  618.         GlobalFree(hCmImage);
  619.         CameraError("LoadPicture", kCmNoMemoryError);
  620.         return 0;
  621.     }
  622.  
  623.     // Allocate memory for picture image
  624.     szImage = (DWORD)pictInfo.width * 3L * (DWORD)pictInfo.height;
  625.     hImage = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, szImage);
  626.     if (hImage == 0)
  627.     {
  628.         GlobalUnlock(hCmImage);
  629.         GlobalFree(hCmImage);
  630.         CameraError("LoadPicture", kCmNoMemoryError);
  631.         return 0;
  632.     }
  633.     pImage = GlobalLock(hImage);
  634.     if (pImage == 0)
  635.     {
  636.         GlobalUnlock(hCmImage);
  637.         GlobalFree(hCmImage);
  638.         GlobalFree(hImage);
  639.         CameraError("LoadPicture", kCmNoMemoryError);
  640.         return 0;
  641.     }
  642.  
  643.     // Convert from compressed picture to picture image
  644.     err = IpInitIPM(ipm);
  645.     if (err == 0)
  646.     {
  647.         err = IpCalculateColorTables(ipm);
  648.         if (err == 0)
  649.         {
  650.             ImageAttribute attr;
  651.             ProgressCallBack ipmCB;
  652.  
  653.             // Prepare image attributes 
  654.             attr.aImgWidth = pictInfo.width;
  655.             attr.aImgLength = pictInfo.height;
  656.             attr.aPixelType = kDIB24;
  657.             attr.aAngle     = kImgRot0;
  658.             attr.aStartingLine = 0;
  659.             attr.aLinesPerBand = pictInfo.height;
  660.             attr.firstBand = TRUE;
  661.             attr.lastBand  = TRUE;
  662.             attr.aCompressionType = pictInfo.dataCompressionMode;
  663.  
  664.             // Setup callback function
  665.             ipmCB.callBackProc = (IpProgressProcPtr)IPMProgressCallback;
  666.             ipmCB.refcon = 0;
  667.  
  668.             err = IpConvertImageToRGB(
  669.                             ipm, 
  670.                             pCmImage, 
  671.                             (unsigned char huge *)pImage, 
  672.                             &attr, 
  673.                             &ipmCB);
  674.         }
  675.         IpEndIPM(ipm);
  676.     }
  677.  
  678.     // Free up compressed picture memory
  679.     GlobalUnlock(hCmImage);
  680.     GlobalFree(hCmImage);
  681.  
  682.     if (err)
  683.     {
  684.         // Report error
  685.         CameraError("LoadPicture", err);
  686.  
  687.         // Free up picture memory
  688.         GlobalUnlock(hImage);
  689.         GlobalFree(hImage);
  690.         return 0;
  691.     }
  692.     else
  693.     {
  694.         GlobalUnlock(hImage);
  695.         return hImage;
  696.     }
  697. }
  698.  
  699.  
  700. /****************************************************************************
  701.  
  702.     FUNCTION:    CameraPaintPicture(HDC, HANDLE, int, int)
  703.  
  704.     PURPOSE:    Paint the picture.
  705.  
  706. ****************************************************************************/
  707. void CameraPaintPicture(HDC hDC, HANDLE hPicture, int x, int y)
  708. {
  709.     BITMAPINFO bmpInfo;
  710.     unsigned char huge *pPicture;
  711.  
  712.     if (!hPicture)
  713.         return;
  714.     bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  715.     bmpInfo.bmiHeader.biWidth = pictInfo.width;
  716.     bmpInfo.bmiHeader.biHeight = pictInfo.height;
  717.     bmpInfo.bmiHeader.biPlanes = 1;
  718.     bmpInfo.bmiHeader.biBitCount = 24;
  719.     bmpInfo.bmiHeader.biCompression = BI_RGB;
  720.     bmpInfo.bmiHeader.biSizeImage = bmpInfo.bmiHeader.biHeight * 
  721.                                     bmpInfo.bmiHeader.biWidth * 3;
  722.     bmpInfo.bmiHeader.biClrUsed = 0;
  723.     bmpInfo.bmiHeader.biClrImportant = 0;
  724.     bmpInfo.bmiHeader.biXPelsPerMeter = 0;
  725.     bmpInfo.bmiHeader.biYPelsPerMeter = 0;
  726.  
  727.     pPicture = GlobalLock(hPicture);
  728.     SetDIBitsToDevice(hDC, x, y, 
  729.                       (WORD)bmpInfo.bmiHeader.biWidth, 
  730.                       (WORD)bmpInfo.bmiHeader.biHeight,
  731.                       0, 0, 0, (WORD)bmpInfo.bmiHeader.biHeight,
  732.                       pPicture, &bmpInfo, DIB_RGB_COLORS);
  733.     GlobalUnlock(hPicture);
  734. }
  735.  
  736. /****************************************************************************
  737.  
  738.     FUNCTION:  CameraError(LPSTR, OSErr)
  739.  
  740.     PURPOSE:  Output camera error and return err code.
  741.  
  742. ****************************************************************************/
  743.  
  744. OSErr CameraError(LPSTR cmdString, OSErr err)
  745. {
  746.     char errString[256];
  747.  
  748.     if (err)
  749.     {
  750.         wsprintf(errString, "%s (%d)", cmdString, err);
  751.         MessageBox(hMainWnd, errString, "Error", MB_ICONEXCLAMATION | MB_OK);
  752.     }
  753.     return err;
  754. }
  755.